[IA64] xen: implemanted domain destruction again
authorawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Fri, 12 May 2006 14:58:56 +0000 (08:58 -0600)
committerawilliam@xenbuild.aw <awilliam@xenbuild.aw>
Fri, 12 May 2006 14:58:56 +0000 (08:58 -0600)
implemented domain destruction.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
xen/arch/ia64/xen/domain.c
xen/include/asm-ia64/linux-xen/asm/pgalloc.h

index 9b2da4da119843bb65e6070ace565b4beb35e8e8..ce06ac1c371418a011ecf6e68e0e09d473ee828b 100644 (file)
@@ -77,12 +77,16 @@ extern void serial_input_init(void);
 static void init_switch_stack(struct vcpu *v);
 void build_physmap_table(struct domain *d);
 
+static void try_to_clear_PGC_allocate(struct domain* d,
+                                      struct page_info* page);
+
 /* this belongs in include/asm, but there doesn't seem to be a suitable place */
 void arch_domain_destroy(struct domain *d)
 {
        struct page_info *page;
        struct list_head *ent, *prev;
 
+       BUG_ON(d->arch.mm->pgd != NULL);
        if (d->arch.mm->pgd != NULL)
        {
                list_for_each ( ent, &d->arch.mm->pt_list )
@@ -395,10 +399,13 @@ static void relinquish_memory(struct domain *d, struct list_head *list)
         /* Follow the list chain and /then/ potentially free the page. */
         ent = ent->next;
 #ifdef CONFIG_XEN_IA64_DOM0_VP
+#if 1
+        BUG_ON(get_gpfn_from_mfn(page_to_mfn(page)) != INVALID_M2P_ENTRY);
+#else
         //XXX this should be done at traversing the P2M table.
-        //BUG_ON(get_gpfn_from_mfn(mfn) != INVALID_M2P_ENTRY);
         if (page_get_owner(page) == d)
             set_gpfn_from_mfn(page_to_mfn(page), INVALID_M2P_ENTRY);
+#endif
 #endif
         put_page(page);
     }
@@ -406,11 +413,112 @@ static void relinquish_memory(struct domain *d, struct list_head *list)
     spin_unlock_recursive(&d->page_alloc_lock);
 }
 
+static void
+relinquish_pte(struct domain* d, pte_t* pte)
+{
+    unsigned long mfn = pte_pfn(*pte);
+    struct page_info* page;
+
+    // vmx domain use bit[58:56] to distinguish io region from memory.
+    // see vmx_build_physmap_table() in vmx_init.c
+    if (((mfn << PAGE_SHIFT) & GPFN_IO_MASK) != GPFN_MEM)
+        return;
+
+    // domain might map IO space or acpi table pages. check it.
+    if (!mfn_valid(mfn))
+        return;
+    page = mfn_to_page(mfn);
+    // struct page_info corresponding to mfn may exist or not depending
+    // on CONFIG_VIRTUAL_FRAME_TABLE.
+    // This check is too easy.
+    // The right way is to check whether this page is of io area or acpi pages
+    if (page_get_owner(page) == NULL) {
+        BUG_ON(page->count_info != 0);
+        return;
+    }
+
+#ifdef CONFIG_XEN_IA64_DOM0_VP
+    if (page_get_owner(page) == d) {
+        BUG_ON(get_gpfn_from_mfn(mfn) == INVALID_M2P_ENTRY);
+        set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
+    }
+#endif
+    try_to_clear_PGC_allocate(d, page);
+    put_page(page);
+}
+
+static void
+relinquish_pmd(struct domain* d, pmd_t* pmd, unsigned long offset)
+{
+    unsigned long i;
+    pte_t* pte = pte_offset_map(pmd, offset);
+
+    for (i = 0; i < PTRS_PER_PTE; i++, pte++) {
+        if (!pte_present(*pte))
+            continue;
+        
+        relinquish_pte(d, pte);
+    }
+    pte_free_kernel(pte_offset_map(pmd, offset));
+}
+
+static void
+relinquish_pud(struct domain* d, pud_t *pud, unsigned long offset)
+{
+    unsigned long i;
+    pmd_t *pmd = pmd_offset(pud, offset);
+    
+    for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
+        if (!pmd_present(*pmd))
+            continue;
+        
+        relinquish_pmd(d, pmd, offset + (i << PMD_SHIFT));
+    }
+    pmd_free(pmd_offset(pud, offset));
+}
+
+static void
+relinquish_pgd(struct domain* d, pgd_t *pgd, unsigned long offset)
+{
+    unsigned long i;
+    pud_t *pud = pud_offset(pgd, offset);
+
+    for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
+        if (!pud_present(*pud))
+            continue;
+
+        relinquish_pud(d, pud, offset + (i << PUD_SHIFT));
+    }
+    pud_free(pud_offset(pgd, offset));
+}
+
+static void
+relinquish_mm(struct domain* d)
+{
+    struct mm_struct* mm = d->arch.mm;
+    unsigned long i;
+    pgd_t* pgd;
+
+    if (mm->pgd == NULL)
+        return;
+
+    pgd = pgd_offset(mm, 0);
+    for (i = 0; i < PTRS_PER_PGD; i++, pgd++) {
+        if (!pgd_present(*pgd))
+            continue;
+
+        relinquish_pgd(d, pgd, i << PGDIR_SHIFT);
+    }
+    pgd_free(mm->pgd);
+    mm->pgd = NULL;
+}
+
 void domain_relinquish_resources(struct domain *d)
 {
     /* Relinquish every page of memory. */
 
-    //XXX relase page traversing d->arch.mm.
+    // relase page traversing d->arch.mm.
+    relinquish_mm(d);
 
     relinquish_memory(d, &d->xenpage_list);
     relinquish_memory(d, &d->page_list);
@@ -746,14 +854,14 @@ assign_domain_page(struct domain *d,
     struct page_info* page = mfn_to_page(physaddr >> PAGE_SHIFT);
     int ret;
 
+    BUG_ON((physaddr & GPFN_IO_MASK) != GPFN_MEM);
     ret = get_page(page, d);
     BUG_ON(ret == 0);
     __assign_domain_page(d, mpaddr, physaddr);
 
     //XXX CONFIG_XEN_IA64_DOM0_VP
     //    TODO racy
-    if ((physaddr & GPFN_IO_MASK) == GPFN_MEM)
-        set_gpfn_from_mfn(physaddr >> PAGE_SHIFT, mpaddr >> PAGE_SHIFT);
+    set_gpfn_from_mfn(physaddr >> PAGE_SHIFT, mpaddr >> PAGE_SHIFT);
 }
 
 #ifdef CONFIG_XEN_IA64_DOM0_VP
index cc62190e55c0c95682ab48b78e90ee1a0cca17ae..5c5561dc24e3f578a29db0a1821b10a14c64b032 100644 (file)
@@ -139,12 +139,14 @@ static inline void pte_free(struct page *pte)
 {
        pgtable_quicklist_free(page_address(pte));
 }
+#endif
 
 static inline void pte_free_kernel(pte_t * pte)
 {
        pgtable_quicklist_free(pte);
 }
 
+#ifndef XEN
 #define __pte_free_tlb(tlb, pte)       pte_free(pte)
 #endif